package top.goldenyear.porpoise.framework.web.core.controller;

import cn.hutool.v7.core.convert.ConvertUtil;
import com.jfinal.kit.StrKit;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.noear.solon.core.Props;
import org.noear.solon.core.PropsConverter;
import org.noear.solon.core.handle.Context;
import org.noear.solon.core.util.MultiMap;
import org.noear.solon.lang.Nullable;
import top.goldenyear.porpoise.common.core.util.convert.ConvertUtils;

/**
 * @author airhead
 */
@Slf4j
public abstract class BaseController {

  protected Context context() {
    return Context.current();
  }

  protected String getStr(String name) {
    return getStr(name, null);
  }

  protected String getStr(String name, String def) {
    return context().paramOrDefault(name, def);
  }

  protected Integer getInt(String name) {
    return getInt(name, null);
  }

  protected Integer getInt(String name, Integer def) {
    return ConvertUtils.toInt(context().param(name), def);
  }

  protected Long getLong(String name) {
    return this.getLong(name, null);
  }

  protected Long getLong(String name, Long def) {
    return ConvertUtils.toLong(context().param(name), def);
  }

  protected Double getDouble(String name) {
    return this.getDouble(name, null);
  }

  protected Double getDouble(String name, Double def) {
    return ConvertUtils.toDouble(context().param(name), def);
  }

  protected BigDecimal getDecimal(String name) {
    return this.getDecimal(name, null);
  }

  protected BigDecimal getDecimal(String name, BigDecimal def) {
    return ConvertUtils.toBigDecimal(context().param(name));
  }

  protected Boolean getBoolean(String name) {
    return this.getBoolean(name, null);
  }

  protected Boolean getBoolean(String name, Boolean def) {
    return ConvertUtils.toBoolean(context().param(name));
  }

  protected <T> T getAs(String name, Class<T> type) {
    return getAs(name, type, null);
  }

  protected <T> T getAs(String name, Class<T> type, T def) {
    String value = context().param(name);
    return ConvertUtil.convert(type, value, def);
  }

  protected <T> T getBean(Class<T> type) {
    T t = this.context().paramAsBean(type);
//    if (Model.class.isAssignableFrom(type)) {
//      if (t != null) {
//        Model<?> model = (Model<?>) t;
//        for (KeyValues<String> values : context().paramMap()) {
//          // 此处通过Map的方式设置
//          model.put(NamingCase.toUnderlineCase(values.getKey()), values.getFirstValue());
//        }
//
//        return t;
//      }
//    }

    return t;
  }

  protected <T> T getModel(Class<T> type) {
    return getModel(type, StrKit.firstCharToLowerCase(type.getSimpleName()));
  }

  protected <T> T getModel(Class<T> type, String name) {
    MultiMap<String> paramMap = context().paramMap();
    return PropsConverter.global().convert(new Props().addAll(paramMap).getProp(name), type);
  }

  protected Map<String, Object> attrMap() {
    return context().attrMap();
  }

  protected <T> T attrOrDefault(String name, T def) {
    return context().attrOrDefault(name, def);
  }

  @Nullable
  protected <T> T attr(String name) {
    return context().attr(name);
  }

  protected void attrSet(String name, Object val) {
    context().attrSet(name, val);
  }

  protected void attrSet(Map<String, Object> map) {
    context().attrSet(map);
  }

  protected void attrsClear() {
    context().attrsClear();
  }

  protected BaseController keepPara() {
    MultiMap<String> map = context().paramMap();
    map.forEach(
        (value) -> {
          String key = value.getKey();
          List<String> values = value.getValues();
          if (values != null && values.size() == 1) {
            attrSet(key, values.get(0));
          } else {
            attrSet(key, values);
          }
        });

    return this;
  }

  protected BaseController keepPara(String... names) {
    for (String name : names) {
      String[] values = context().paramValues(name);
      if (values != null) {
        if (values.length == 1) {
          attrSet(name, values[0]);
        } else {
          attrSet(name, values);
        }
      }
    }

    return this;
  }

  protected BaseController keepPara(Class<?> type, String name) {
    String[] values = context().paramValues(name);
    if (values != null) {
      if (values.length == 1) {
        attrSet(name, ConvertUtil.convert(type, values[0]));
      } else {
        attrSet(name, values);
      }
    }

    return this;
  }

  protected BaseController keepPara(Class<?> type, String... names) {
    if (type == String.class) {
      return this.keepPara(names);
    } else {
      if (names != null) {
        for (String name : names) {
          this.keepPara(type, name);
        }
      }

      return this;
    }
  }
}
